package org.wu.framework.easy.markdown.web;


import org.wu.framework.easy.markdown.adapter.ExcelMarkDownAdapter;
import org.wu.framework.easy.markdown.endpoint.EasyMarkDownPoint;
import org.wu.framework.easy.markdown.endpoint.convert.EasyMarkDownPointConvert;
import org.wu.framework.easy.markdown.stereotype.markdown.EasyMarkDown;
import org.wu.framework.easy.markdown.toolkit.DynamicEasyMarkDownContextHolder;
import org.wu.framework.core.NormalUsedString;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.wu.framework.core.utils.ObjectUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;

/**
 * description markdown 导出拦截
 *
 * @author Jia wei Wu
 */
@RestControllerAdvice
public class MarkDownResponseHandler implements ResponseBodyAdvice<Object> {
    private final ExcelMarkDownAdapter excelExcelServiceAdapter=new ExcelMarkDownAdapter();

    private final EasyMarkDownPointConvert easyMarkDownPointConvert=new EasyMarkDownPointConvert();

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return AnnotatedElementUtils.getMergedAnnotation(methodParameter.getMethod(), EasyMarkDown.class) != null
                || AnnotatedElementUtils.getMergedAnnotation(methodParameter.getMethod().getDeclaringClass(), EasyMarkDown.class) != null;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
                                  MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        EasyMarkDown easyMarkDown = AnnotatedElementUtils.findMergedAnnotation(Objects.requireNonNull(methodParameter.getMethod()), EasyMarkDown.class);

        EasyMarkDownPoint easyMarkDownPoint = easyMarkDownPointConvert.converter(easyMarkDown);
        EasyMarkDownPoint peek = DynamicEasyMarkDownContextHolder.peek();
        easyMarkDownPoint = ObjectUtils.isEmpty(peek) ? easyMarkDownPoint : peek;

        String fileName = easyMarkDownPoint.getFileName();
        String suffix = easyMarkDownPoint.getSuffix();
        DynamicEasyMarkDownContextHolder.clear();
        Collection<?> collection;
        if (o instanceof Collection) {
            collection = (Collection<?>) o;
        } else {
            collection = Collections.singletonList(o);
        }
        HttpHeaders headers = serverHttpResponse.getHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        String encodedFileName = null;
        encodedFileName = java.net.URLEncoder.encode(fileName, StandardCharsets.UTF_8);
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s.%s\"; filename*=utf-8''%s.%s", encodedFileName, suffix, encodedFileName, suffix));
        headers.add("File-Name", encodedFileName + NormalUsedString.DOT + suffix);
        headers.add(HttpHeaders.PRAGMA, "no-cache");
        headers.add(HttpHeaders.EXPIRES, "0");
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);

        byte[] bytes = excelExcelServiceAdapter.exportMarkDown(collection);
        try {
            OutputStream body = serverHttpResponse.getBody();
            body.write(bytes);
            body.flush();
            body.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
        return o;
    }
}